<?php


namespace App\Console\Commands;


use App\Http\Controllers\AdminBaseController;
use App\Models\AdminMenuModel;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
use function Psy\debug;

//php artisan make:code
//api_class_name api的控制器  admin_class_name  admin控制器  demo_table 表面


class GenerationAdminMenu extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'create:menu {m} {path?}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Create all menu';
    protected $name_namespace = "App\Http\Controllers\\";
    protected $modelName = "App\Models\AdminMenuModel";


    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     */
    public function handle()
    {

        $m = $this->argument('m');
        $path = $this->argument('path');
        $path = $path ?: "";
        switch (strtoupper($m)){
            case "MASTER":
                $this->modelName = "App\Models\Master\MasterMenuModel";
                break;
            case "ADMIN":
                $this->modelName = "App\Models\AdminMenuModel";
                break;
            default:

        }
        // 获取路径下面所有的文件
        $this->getFilesToPath($m, $path);


    }


    protected function getFilesToPath($m, $path)
    {
        $dir = app_path('Http' . DIRECTORY_SEPARATOR . 'Controllers' . DIRECTORY_SEPARATOR . $m . DIRECTORY_SEPARATOR . $path);
        if (is_dir($dir)) {
            $opendir = opendir($dir);
            while ($file = readdir($opendir)) {
                if ($file != '.' && $file != '..') {
                    $this->getFilesToPath($m, $path . DIRECTORY_SEPARATOR . $file);
                }
            }
            closedir($opendir);
        } elseif (is_file($dir)) {
            $this->createdData($m, $path);
        }

    }

    function createdData($m, $path)
    {
        $m = strtolower($m);
        $path = str_replace(".php", '', $path);     // 去掉后缀
        $path = trim($path, DIRECTORY_SEPARATOR);                   //去掉前后的分隔符
        $path = explode(DIRECTORY_SEPARATOR, $path);

        //模块名称+路径名称作为module
        // 文件名去除后缀作为controller
        $class = $this->name_namespace . Str::ucfirst($m) . "\\" .implode("\\", $path);
        $this->line($class);
        $path = array_map([Str::class, 'snake'], array_map('lcfirst', $path));         // 选转小写 再转下划线

        $controller = array_pop($path);
        if (empty($controller)) {
            $this->line('生成错误：' . $m . "\\" . implode("\\", $path));
            return;
        }
        $module = $m . "\\" . implode("\\", $path);

        $pid = $this->getPid($m, $path);
        //module+controller作为命名空间实例化类 获取类里面所有方法

        $methods = get_class_methods($class);
        $base_methods = get_class_methods($this->name_namespace . 'Controller');
        // 每个方法生成一条记录;  跳过 form，lock getServices downloadFile failure success detail lists destroy update
        $skip_methods = ['form', 'lock', 'getServices', 'downloadFile', 'failure', 'success', 'detail', 'lists', 'delete', 'update'];
        $methods = array_diff($methods, $base_methods, $skip_methods);

        $pid = $this->saveMenu($module, $controller, "*", $pid);         //保存控制器通用方法

        foreach ($methods as $method) {
            if (Str::contains($method, ['__'])) {
                continue;
            }
            // 其中  [detail, show] [lists, index] [destroy, delete] [store, update] 关联生成 method字段和other_method
            // 其中 名称直接显示对应的url路由 text : AdminUsers/index
            // 按目录层级生成pid
            // 每个controller 生成一个 method 为 * 的数据 作为子方法的父级
            // 检查数据库是否存在当前记录 存在跳过
            $this->saveMenu($module, $controller, $method, $pid);
        }
    }


    public function getPid($m, $path)
    {
        if (empty($path)) {
            return 0;
        }
        $dir_path = $m;
        $pid = 0;
        foreach ($path as $value) {
            // 搜索或者创建对应的目录数据并返回pid
            // 将pid作为下一次创建用的pid继续循环
            // 返回最后一个目录的pid
            $dir_path .= "\\$value";
            $pid = $this->saveMenu($dir_path, $value, "", $pid);
        }
        return $pid;
    }

    public function saveMenu($module, $controller, $method, $pid)
    {
        $method = empty($method) ? "" : Str::snake($method);
        $controller = str_replace('_controller', '', $controller);
        $module = trim($module, "\\");

        $admin_menu =  app($this->modelName)::where('module', $module)->where('controller', $controller)->where('method', $method)->first();
        if ($admin_menu) {
            return $admin_menu->id;
        }
        $admin_menu =  app($this->modelName);
        $admin_menu->text = trim($controller . '\\' . $method, '\\');
        $admin_menu->module = $module;
        $admin_menu->controller = $controller;
        $admin_menu->method = $method;
        $admin_menu->other_method = match ($method) {
            'show' => 'detail',
            'index' => 'lists',
            'destroy' => 'delete',
            'store' => 'update',
            default => '',
        };
        $admin_menu->pid = $pid;
        $admin_menu->save();
        return $admin_menu->id;
    }
}
